﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using HisoftSmart.Client.AutomationClient.Helpers;

namespace HisoftSmart.Client.AutomationClient.Actions
{
    public class InvokeTapAction : ActionBase
    {
        public readonly List<Func<AutomationPeer, bool>> PatternTesters;
        public readonly List<Func<UIElement, bool>> UIElementTesters;

        public InvokeTapAction(string name, string _params)
            : base(name, _params)
        {
            var providers =
                from method in typeof(InvokeTapAction).GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
                where method.ReturnType == typeof (bool)
                      && method.GetParameters().Length == 1
                      && method.GetParameters()[0].ParameterType == typeof (AutomationPeer)
                select new Func<AutomationPeer,bool>((AutomationPeer peer) => (bool)method.Invoke(null, new object[] {peer}));

            PatternTesters = new List<Func<AutomationPeer, bool>>(providers);
            UIElementTesters = new List<Func<UIElement, bool>>();
        }

        private AutomationIdentifier CreateAutomationIdentifier(string id)
        {
            return new AutomationIdentifier(id, AutomationIdentification.TryDisplayedText);
        }

        protected override void DoImpl()
        {
            AutomationIdentifier = CreateAutomationIdentifier(this.Params);
            var element = AutomationElementFinder.FindElement(AutomationIdentifier);
            if (element == null)
            {
                SendFailedResult();
                return;
            }

            // automate the click
            var peer = AutomationPeerCreator.GetPeer(element);
            if (peer == null)
                throw new Exception("No automation peer found for " + element.GetType().FullName);

            foreach (var patternTester in PatternTesters)
            {
                if (patternTester(peer))
                {
                    SendSuccessResult();
                    return;
                }
            }

            foreach (var uiElementTester in UIElementTesters)
            {
                if (uiElementTester(element))
                {
                    SendSuccessResult();
                    return;
                }
            }

            SendFailedResult();
        }

        private static bool TryInvokePatternAutomation(AutomationPeer peer)
        {
            var pattern = peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
            if (pattern == null)
                return false;

            try
            {
                pattern.Invoke();
            }
            catch (Exception exception)
            {
                throw new Exception("Exception while invoking pattern", exception);
            }

            return true;
        }

        private static bool TryTogglePatternAutomation(AutomationPeer peer)
        {
            var pattern = peer.GetPattern(PatternInterface.Toggle) as IToggleProvider;
            var pattern2 = peer.GetPattern(PatternInterface.Toggle) as ITextProvider;
            if (pattern == null)
                return false;

            try
            {
                pattern.Toggle();
            }
            catch (Exception exception)
            {
                throw new Exception("Exception while invoking pattern", exception);
            }

            return true;
        }
    }
}
